# Reksio - Memory Map Editor
# Copyright (C) 2023 CERN
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# In applying this licence, CERN does not waive the privileges and immunities
# granted to it by virtue of its status as an Intergovernmental Organization or
# submit itself to any jurisdiction.

import reksio

import validate_name

def validate(node):
    attr = node.getAttribute('name')
    valid = validate_name.validate(attr)
    return valid and validate_pci_device_info(node) and validate_xdrv_edge(node)


def getMessage():
	return "Map validator error msg"


def validate_pci_device_info(node):
	result = True

	root_map = node.getRoot().children().pop()
	edge_bus_type = node.getAttribute(['x-driver-edge', 'bus-type'])

	if root_map == node and edge_bus_type is not None:

		if edge_bus_type.value == 'PCI':
			vendor_id = node.getAttribute(['x-driver-edge', 'pci-device-info', 'vendor-id'])
			device_id = node.getAttribute(['x-driver-edge', 'pci-device-info', 'device-id'])

			if vendor_id is None:
				reksio.warn(
					f'For PCI bus, the "{root_map.name}/x-driver-edge/pci-device-info/vendor-id" must be specified!')
				result = False
			elif vendor_id.value == '0x0':
				reksio.warn(
					f'For PCI bus, the "{root_map.name}/x-driver-edge/pci-device-info/vendor-id" value is not defined!')
				result = False

			if device_id is None:
				reksio.warn(
					f'For PCI bus, the "{root_map.name}/x-driver-edge/pci-device-info/device-id" must be specified!')
				result = False
			elif device_id.value == '0x0':
				reksio.warn(
					f'For PCI bus, the "{root_map.name}/x-driver-edge/pci-device-info/device-id" value is not defined!')
				result = False

	return result



def validate_xdrv_edge(node):
    """
    Top map validator for x-driver-edge attribute container.

    When x-driver-edge is defined for a top memory map, the 'bus-type' attribute is required
    to generate EDGE drivers.
    """
    root = node.getRoot().children().pop()

    # Skip for all submaps, x-driver-edge is only required for the root map
    if not root == node:
        return True

    # Skip if the attribute container 'x-driver-edge' is not defined
    is_xedge = any(attr.fullname.startswith('x-driver-edge') for attr in root.attributes())
    bus_type = root.getAttribute(['x-driver-edge', 'bus-type'])

    if is_xedge and not bus_type:
        reksio.warn(f'"{root.name}/x-driver-edge/bus-type" is not defined!')
        return False

    return True
